package com.example;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.time.OffsetDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.vo.CommandLineArgs;
import com.example.vo.NexusAssetInfo;

/**
 * 解析assets并下载文件，然后保存到H2数据库
 */
public class AssetDownloader {
    private static final String DB_URL = "jdbc:h2:./assets_db";
    private static final String DB_USER = "sa";
    private static final String DB_PASSWORD = "";
    private static final String DOWNLOAD_DIR = "./downloaded_assets";

    public static void main(String[] args) {
        try {
            // 解析命令行参数
            CommandLineArgs cmdArgs = HttpUtils.parseCommandLineArgs(args);

            HttpUtils.checkRequiredParams(cmdArgs);
            // 初始化数据库
            initDatabase();

            // 创建下载目录
            File downloadDir = new File(DOWNLOAD_DIR);
            if (!downloadDir.exists()) {
                downloadDir.mkdirs();
            }

            // 下载文件并保存到数据库
            int downloadedCount = 0;
            int failedCount = 0;
            int totalAssetsCount = 0;

            // 遍历并处理nexus_pages目录下的所有JSON文件
            List<File> sortedJsonFiles = getSortedJsonFilesInDirectory("./nexus_pages");
            System.out.println("找到 " + sortedJsonFiles.size() + " 个JSON文件需要处理");
            
            int fileIndex = 0;
            for (File jsonFile : sortedJsonFiles) {
                fileIndex++;
                try {
                    System.out.println("\n开始处理文件 " + fileIndex + "/" + sortedJsonFiles.size() + ": " + jsonFile.getName());
                    List<NexusAssetInfo> assets = parseJsonFile(jsonFile.getPath());
                    int fileAssetsCount = assets.size();
                    totalAssetsCount += fileAssetsCount;
                    System.out.println("解析到 " + fileAssetsCount + " 个assets对象");
                    
                    int fileDownloadedCount = 0;
                    int fileFailedCount = 0;
                    
                    for (NexusAssetInfo asset : assets) {
                        try {
                            // 检查资产是否已存在于数据库中
                            if (checkAssetExists(asset.getId())) {
                                System.out.println("资产已存在于数据库中，跳过下载: " + asset.getPath());
                                continue;
                            }
                            
                            System.out.println("正在下载: " + asset.getPath());
                            String localFilePath = downloadFile(asset.getDownloadUrl(), asset.getPath(), cmdArgs);
                            saveAssetToDatabase(asset);
                            downloadedCount++;
                            fileDownloadedCount++;
                            System.out.println("下载成功并保存到数据库: " + asset.getPath());
                        } catch (Exception e) {
                            failedCount++;
                            fileFailedCount++;
                            System.err.println("下载失败: " + asset.getPath() + ", 错误: " + e.getMessage());
                        }
                    }
                    
                    System.out.println("文件 " + jsonFile.getName() + " 处理完成。成功: " + fileDownloadedCount + ", 失败: " + fileFailedCount);
                } catch (Exception e) {
                    System.err.println("处理文件 " + jsonFile.getName() + " 失败: " + e.getMessage());
                    e.printStackTrace();
                }
            }

            System.out.println("\n所有下载任务完成。总共解析到: " + totalAssetsCount + " 个assets对象，成功: " + downloadedCount + ", 失败: " + failedCount);

        } catch (Exception e) {
            System.err.println("[ERROR] " + e.getMessage());
            e.printStackTrace();
            HttpUtils.showHelp();
            System.exit(1);
        }
    }

    /**
     * 初始化H2数据库
     */
    private static void initDatabase() throws SQLException {
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement()) {
            // 创建assets表
            stmt.execute("CREATE TABLE IF NOT EXISTS assets (" +
                    "id VARCHAR(100) PRIMARY KEY, " +
                    "content_type VARCHAR(100), " +
                    "download_url VARCHAR(500), " +
                    "last_modified TIMESTAMP, " +
                    "md5 VARCHAR(50), " +
                    "path VARCHAR(500), " +
                    "sha1 VARCHAR(50), " +
                    "size BIGINT, " +
                    "download_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");
        }
    }

    /**
     * 解析JSON文件获取assets列表
     */
    private static List<NexusAssetInfo> parseJsonFile(String filePath) throws IOException {
        List<NexusAssetInfo> assets = new ArrayList<>();

        // 读取JSON文件内容
        String jsonContent = new String(Files.readAllBytes(Paths.get(filePath)));
        JSONObject jsonObject = JSON.parseObject(jsonContent);
        JSONArray files = jsonObject.getJSONArray("files");

        // 遍历files数组
        for (int i = 0; i < files.size(); i++) {
            JSONObject file = files.getJSONObject(i);
            JSONArray fileAssets = file.getJSONArray("assets");

            // 遍历assets数组
            for (int j = 0; j < fileAssets.size(); j++) {
                JSONObject assetJson = fileAssets.getJSONObject(j);
                NexusAssetInfo asset = new NexusAssetInfo();
                asset.setId(assetJson.getString("id"));
                asset.setContentType(assetJson.getString("contentType"));
                asset.setDownloadUrl(assetJson.getString("downloadUrl"));
                asset.setLastModified(assetJson.getString("lastModified"));
                asset.setMd5(assetJson.getString("md5"));
                asset.setPath(assetJson.getString("path"));
                asset.setSha1(assetJson.getString("sha1"));
                asset.setSize(assetJson.getLong("size"));
                
                assets.add(asset);
            }
        }

        return assets;
    }

    /**
     * 下载文件
     */
    private static String downloadFile(String downloadUrl, String path, CommandLineArgs cmdArgs) throws Exception {
        // 构建本地保存路径
        String localFilePath = DOWNLOAD_DIR + File.separator + path;
        File localFile = new File(localFilePath);
        File localDir = localFile.getParentFile();

        // 创建必要的目录结构
        if (!localDir.exists()) {
            localDir.mkdirs();
        }

        // 使用HttpUtils下载文件，传入代理设置等参数
        HttpUtils.downloadFile(
            downloadUrl,
            localFilePath,
            cmdArgs.getUsername(),
            cmdArgs.getPassword(),
            cmdArgs.getProxyHost(),
            cmdArgs.getProxyPort(),
            cmdArgs.getProxyUsername(),
            cmdArgs.getProxyPassword()
        );

        return localFilePath;
    }

    /**
     * 获取目录下所有JSON文件并按文件名排序
     */
    private static List<File> getSortedJsonFilesInDirectory(String directoryPath) {
        List<File> jsonFiles = new ArrayList<>();
        File directory = new File(directoryPath);
        
        // 检查目录是否存在
        if (!directory.exists() || !directory.isDirectory()) {
            System.err.println("目录不存在或不是有效的目录: " + directoryPath);
            return jsonFiles;
        }
        
        // 获取所有.json文件
        File[] files = directory.listFiles((dir, name) -> name.toLowerCase().endsWith(".json"));
        if (files != null) {
            // 添加到列表
            jsonFiles.addAll(Arrays.asList(files));
            
            // 按文件名排序（假设文件名是page_1.json, page_2.json等格式）
            jsonFiles.sort(Comparator.comparing(File::getName, (name1, name2) -> {
                try {
                    // 尝试提取文件名中的数字进行排序
                    int num1 = extractNumberFromFileName(name1);
                    int num2 = extractNumberFromFileName(name2);
                    return Integer.compare(num1, num2);
                } catch (Exception e) {
                    // 如果无法提取数字，则按字母顺序排序
                    return name1.compareTo(name2);
                }
            }));
        }
        
        return jsonFiles;
    }
    
    /**
     * 从文件名中提取数字，用于排序
     */
    private static int extractNumberFromFileName(String fileName) {
        // 尝试从文件名中提取数字，例如"page_1.json"中的1
        Matcher matcher = Pattern.compile("\\d+").matcher(fileName);
        if (matcher.find()) {
            return Integer.parseInt(matcher.group());
        }
        return 0; // 如果没有找到数字，返回0
    }

    /**
     * 检查资产是否已存在于数据库中
     */
    private static boolean checkAssetExists(String assetId) throws SQLException {
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement(
                     "SELECT id FROM assets WHERE id = ?")) {
            
            pstmt.setString(1, assetId);
            try (java.sql.ResultSet rs = pstmt.executeQuery()) {
                return rs.next(); // 如果结果集有记录，则资产已存在
            }
        }
    }
    
    /**
     * 保存asset到数据库
     */
    private static void saveAssetToDatabase(NexusAssetInfo asset) throws SQLException {
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement(
                     "INSERT INTO assets (id, content_type, download_url, last_modified, md5, path, sha1, size) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")) {
            
            // 设置INSERT参数
            pstmt.setString(1, asset.getId());
            pstmt.setString(2, asset.getContentType());
            pstmt.setString(3, asset.getDownloadUrl());
            pstmt.setTimestamp(4, convertStringToTimestamp(asset.getLastModified()));
            pstmt.setString(5, asset.getMd5());
            pstmt.setString(6, asset.getPath());
            pstmt.setString(7, asset.getSha1());
            pstmt.setLong(8, asset.getSize());
            pstmt.executeUpdate();
        }
    }

    /**
     * 转换String时间到Timestamp
     */
    private static Timestamp convertStringToTimestamp(String dateString) {
        try {
            // 解析ISO 8601格式的字符串为OffsetDateTime
            OffsetDateTime offsetDateTime = OffsetDateTime.parse(dateString);
            return Timestamp.from(offsetDateTime.toInstant());
        } catch (Exception e) {
            System.err.println("时间格式转换失败: " + dateString);
            return new Timestamp(System.currentTimeMillis());
        }
    }


}